package com.inforich.app.api.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.inforich.app.api.dto.BookingAllocationDTO;
import com.inforich.app.api.dto.BookingDTO;
import com.inforich.app.api.service.IAppBookingService;
import com.inforich.app.api.service.IAppProjectService;
import com.inforich.app.api.service.IAppTransportService;
import com.inforich.app.api.vo.BookingVO;
import com.inforich.app.component.LoginUserApp;
import com.inforich.appManage.service.IContactService;
import com.inforich.carManage.domain.Driver;
import com.inforich.carManage.service.IDriverService;
import com.inforich.common.constant.ProjectConstants;
import com.inforich.common.core.domain.AjaxResult;
import com.inforich.common.enums.ApproveEnum;
import com.inforich.common.enums.BookingEnum;
import com.inforich.common.utils.DateUtils;
import com.inforich.common.utils.DictUtils;
import com.inforich.orderManage.domain.Booking;
import com.inforich.orderManage.domain.BookingDriverDrivers;
import com.inforich.orderManage.domain.Transport;
import com.inforich.orderManage.service.IBookingDriverDriversService;
import com.inforich.orderManage.service.IBookingService;
import com.inforich.orderManage.service.ITransportService;
import com.inforich.projectManage.domain.Project;
import com.inforich.projectManage.domain.ProjectRubbishExpand;
import com.inforich.projectManage.domain.ProjectRubbishRemoval;
import com.inforich.projectManage.service.IProjectRubbishExpandService;
import com.inforich.projectManage.service.IProjectRubbishRemovalService;
import com.inforich.projectManage.service.IProjectService;
import java.text.ParseException;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @description: some desc
 * @author: HJM
 * @date: 2022/10/31
 */
@Service
public class AppBookingServiceImpl implements IAppBookingService {

  @Autowired
  private IBookingService bookingService;
  @Autowired
  private IAppProjectService appProjectService;
  @Autowired
  private IProjectService projectService;
  @Autowired
  private ITransportService transportService;
  @Autowired
  private IContactService contactService;
  @Autowired
  private IProjectRubbishExpandService projectRubbishExpandService;
  @Autowired
  private IProjectRubbishRemovalService projectRubbishRemovalService;
  @Autowired
  private IDriverService driverService;
  @Autowired
  private IBookingDriverDriversService bookingDriverDriversService;
  @Autowired
  private IAppTransportService appTransportService;

  @Override
  public BookingVO getInfo(String id) {
    BookingVO vo = new BookingVO();
    Booking booking = bookingService.getBookingById(id);
    BeanUtils.copyProperties(booking, vo);
    Project project = projectService.getProjectById(booking.getProjectId());

    vo.setProjectAddress(project.getAddress());
    vo.setProjectKindId(project.getProjectKindId());

    List<Transport> transportList = transportService.listByBookingId(id);
    vo.setTransportList(transportList);

    return vo;
  }

  @Override
  public AjaxResult addBooking(LoginUserApp loginUserApp, BookingDTO bookingDTO) {
    Project project = appProjectService.getMyProject(loginUserApp);
    if (project == null) {
      return AjaxResult.error("请先进行项目认证");
    }
    String projectId = project.getId();
    Long projectKindId = project.getProjectKindId();
    // 资源化利用单位
    Long disposalLandId = null;
    // 运输企业
    String transportCompanyId = null;
    // 判断是否审批成功
    if (ProjectConstants.PROJECT_KIND_EXPAND.equals(projectKindId)
        || ProjectConstants.PROJECT_KIND_RENOVATION.equals(projectKindId)) {
      ProjectRubbishExpand rubbishExpand = projectRubbishExpandService.getProjectRubbishExpandByProjectId(
          projectId);
      if (rubbishExpand == null) {
        return AjaxResult.error("请先进行新扩改登记");
      }
      if (!ApproveEnum.PASS.getDbData().equals(rubbishExpand.getApprovalStatus())) {
        return AjaxResult.error("新扩改登记尚未审批通过");
      }
      disposalLandId = rubbishExpand.getDisposalLandId();
      transportCompanyId = rubbishExpand.getTransportCompanyId();
    }
    if (ProjectConstants.PROJECT_KIND_REMOVAL.equals(projectKindId)) {
      ProjectRubbishRemoval rubbishRemoval = projectRubbishRemovalService.getProjectRubbishRemovalByProjectId(
          projectId);
      if (rubbishRemoval == null) {
        return AjaxResult.error("请先进行拆迁备案登记");
      }
      if (!ApproveEnum.PASS.getDbData().equals(rubbishRemoval.getApprovalStatus())) {
        return AjaxResult.error("拆迁备案尚未审批通过");
      }
      disposalLandId = rubbishRemoval.getDisposalLandId();
      transportCompanyId = rubbishRemoval.getTransportCompanyId();
    }

    Date now = DateUtils.toDate(LocalDate.now());
    if (bookingDTO.getBookingTime().before(now)) {
      return AjaxResult.error("请选择正确的预约时间");
    }

    Booking booking = new Booking();
    BeanUtils.copyProperties(bookingDTO, booking);
    booking.setProjectId(projectId);
    booking.setCarType(
        DictUtils.getDictLabel("car_type_id", String.valueOf(bookingDTO.getCarTypeClassId())));
    booking.setLocation(project.getLocation());
    booking.setDisposalLandId(disposalLandId);
    booking.setTransportCompanyId(transportCompanyId);
    // 默认为待分配
    booking.setState(Long.valueOf(BookingEnum.ALLOCATED.getDbData()));
    return AjaxResult.success(bookingService.insertBooking(booking));
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public AjaxResult allocationBooking(LoginUserApp loginUserApp, BookingAllocationDTO dto) {
    // 公司ID
    String transportCompanyId = contactService.getTransportCompanyIdByAppUserId(
        loginUserApp.getId());
    // 预约单
    Booking booking = bookingService.getBookingById(dto.getBookingId());
    if (!booking.getTransportCompanyId().equals(transportCompanyId)) {
      return AjaxResult.error("不可处理非本公司预约单");
    }
    if (!BookingEnum.ALLOCATED.getDbData().equals(booking.getState().intValue())) {
      return AjaxResult.error("只有待分配的预约单才可分配司机");
    }
    // 分配的司机列表
    List<Driver> driverList = driverService.list(new LambdaQueryWrapper<Driver>()
        .eq(Driver::getTransportCompanyId, transportCompanyId)
        .in(Driver::getId, dto.getDriverIds()));
    if (CollUtil.isEmpty(driverList)) {
      return AjaxResult.error("无可用的司机");
    }
    for (Driver driver : driverList) {
      BookingDriverDrivers brr = new BookingDriverDrivers();
      brr.setBookingId(dto.getBookingId());
      brr.setDriverId(driver.getId());
      bookingDriverDriversService.save(brr);
    }
    // 修改预约单状态为进行中
    bookingService.update(new LambdaUpdateWrapper<Booking>()
        .set(Booking::getState, BookingEnum.CONDUCT.getDbData())
        .eq(Booking::getId, dto.getBookingId()));
    return AjaxResult.success();
  }

  @Override
  public BookingVO queryMyBookingInfo(LoginUserApp loginUserApp, String bookingId) {
    // 预约单信息
    BookingVO vo = new BookingVO();
    Booking booking = bookingService.getBookingById(bookingId);
    BeanUtils.copyProperties(booking, vo);
    // 项目信息
    Project project = projectService.getProjectById(booking.getProjectId());
    vo.setProjectAddress(project.getAddress());
    vo.setProjectKindId(project.getProjectKindId());
    // 运输单信息
    Long driverId = contactService.getDriverIdByAppUserId(loginUserApp.getId());
    List<Transport> transportList = transportService.listByBookingIdAndDriverId(bookingId,
        driverId);
    vo.setTransportList(transportList);

    String transportStatus = appTransportService.getBookingStatus(booking);
    if (StrUtil.isNotBlank(transportStatus)) {
      vo.setTransportStatus(transportStatus);
    } else {
      if (CollUtil.isEmpty(transportList)) {
        vo.setTransportStatus("开始发车");
      } else {
        Transport transport = transportList.get(0);
        vo.setTransportStatus(transport.getEndTime() == null ? "运输结束" : "开始发车");
      }
    }
    return vo;
  }

}
